package cn.net.withub.dataCollector.dao.impl;

import cn.net.withub.dataCollector.dao.DaoTool;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.jdbc.Work;
import org.hibernate.transform.Transformers;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.Map;


@SuppressWarnings("unchecked")
public class DaoToolImpl implements DaoTool {

	private SessionFactory sessionFactory;


	public void deleteObject(Object model) {
		getSession().delete(model);
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	public Session getSession() {
		return sessionFactory.getCurrentSession();
//		return sessionFactory.openSession();
	}


	public <T> void save(T t) {
		getSession().save(t);
	}

	public <T> void saveOrUpdate(T t) {
		getSession().saveOrUpdate(t);
	}

	public <T> void delete(T t) {
		getSession().delete(t);
	}

	public <T> void deleteLog(T t) {
		getSession().delete(t);
	}

	public <T> void delete(Class<T> entityClass, String id) {
		getSession().delete(get(entityClass, id));
	}

	public <T> void saveLog(T t) {
		getSession().save(t);
	}

	public <T> void saveOrUpdateLog(T t) {
		getSession().saveOrUpdate(t);
	}


	public <T> void update(T t) {
		getSession().update(t);
	}


	public <T, PK extends Serializable> T get(Class<T> entityClass, PK id) {
		return (T) getSession().get(entityClass, id);

	}

	public <T> List<T> findAll(String hql, Class<T> entityClass) {
		return findAll(hql, entityClass, new Object[] {});
	}


	public <T> List<T> findAll(String hql, Class<T> entityClass, Object param) {
		return findAll(hql, entityClass, new Object[] { param });
	}


	public <T> List<T> findAll(String hql, Class<T> entityClass, Object[] params) {
		Query query = getSession().createQuery(hql);
		for (int i = 0; i < params.length; i++) {
			query.setParameter(i, params[i]);
		}
		return (List<T>) query.list();
	}


	public <T> List<T> findByPage(final String hql, Class<T> entityClass,
								  final int firstResult, final int maxResult) {
		return findByPage(hql, entityClass, new Object[] {}, firstResult,
				maxResult);
	}


	public <T> List<T> findByPage(final String hql, Class<T> entityClass,
								  final Object param, final int firstResult, final int maxResult) {
		return findByPage(hql, entityClass, new Object[] { param },
				firstResult, maxResult);
	}


	public <T> List<T> findByPage(final String hql, Class<T> entityClass,
								  final Object[] params, final int firstResult, final int maxResult) {
		Query query = getSession().createQuery(hql);
		for (int i = 0; i < params.length; i++) {
			query.setParameter(i, params[i]);
		}
		query.setFirstResult(firstResult);
		query.setMaxResults(maxResult);
		return (List<T>) query.list();
	}

	public <T> void merge(T t) {
		getSession().merge(t);

	}

	public SQLQuery createSQLQuery(String sql) {
		return getSession().createSQLQuery(sql);
	}

	public Query createHQLQuery(String hql) {
		return getSession().createQuery(hql);
	}

	public <T> List<T> findList(String hql, Object... params) {
		Query query = sessionFactory.getCurrentSession().createQuery(hql);
		if(params!=null&&params.length>0){
			query = setQueryParams(query,params);
		}
		return query.list();
	}

	private Query setQueryParams(final Query query,final Object... params){
		for(int i=0;i<params.length;i++){
			Object obj = params[i];
			if (obj instanceof String) {
				String o = (String) obj;
				query.setString(i, o);
			} else if (obj instanceof Double) {
				Double o = (Double) obj;
				query.setDouble(i, o);
			} else if (obj instanceof Long) {
				Long o = (Long) obj;
				query.setLong(i,o);
			} else if (obj instanceof Integer) {
				Integer o = (Integer) obj;
				query.setInteger(i,o);
			} else if (obj instanceof Date) {
				Date o = (Date) obj;
				query.setDate(i,o);
			}else if (obj instanceof Short) {
				Short o = (Short) obj;
				query.setShort(i,o);
			} else {
				query.setString(i,obj==null?null:obj.toString());
			}
		}
		return query;
	}


	public <T> List<T> findSQLList(String sql,Class entityClass,int page,int pageSize, Object... params) {
		Query query = null;
		if(entityClass!=null){
			if(Map.class.isAssignableFrom(entityClass)){
				query = sessionFactory.getCurrentSession().createSQLQuery(sql);
				query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
			}else{
				query = sessionFactory.getCurrentSession().createSQLQuery(sql).addEntity(entityClass);
			}
		}else{
			query = sessionFactory.getCurrentSession().createSQLQuery(sql);
		}
		if(params!=null&&params.length>0){
			query = setQueryParams(query,params);
		}
		return query.setFirstResult((page-1)*pageSize).setMaxResults(pageSize).list();
	}

	public <T> List<T> findList(String hql,int page,int pageSize,Object... params) {
		Query query = sessionFactory.getCurrentSession().createQuery(hql);
		if(params!=null&&params.length>0){
			query = setQueryParams(query,params);
		}
		return query.setFirstResult((page-1)*pageSize).setMaxResults(pageSize).list();
	}

	public List findSQLList(String sql,Class entityClass, Object... params) {
		Query query = null;
		if(entityClass!=null){
			if(Map.class.isAssignableFrom(entityClass)){
				query = sessionFactory.getCurrentSession().createSQLQuery(sql);
				query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
			}else{
				query = sessionFactory.getCurrentSession().createSQLQuery(sql).addEntity(entityClass);
			}
		}else{
			query = sessionFactory.getCurrentSession().createSQLQuery(sql);
		}
		if(params!=null&&params.length>0){
			query = setQueryParams(query,params);
		}
		return query.list();
	}

	public Session getCurrentSession(){
		return sessionFactory.getCurrentSession();
	}

	public void execute(final String sql){
		getSession().getTransaction();
		getSession().doWork(new Work() {
			public void execute(Connection connection) throws SQLException {
				PreparedStatement ps = null;
				ResultSet rs = null;
				try {
					ps = connection.prepareStatement( sql );
					ps.execute();
				}
				finally {
					this.doClose(null,ps,rs);
				}

			}
			private void doClose(Session session, PreparedStatement stmt,ResultSet rs) {
				//当Hibernate的事务由Spring接管时,session的关闭由Spring管理.不用手动关闭
				if(rs != null){
					try {
						rs.close();
						rs=null;
					} catch (Exception ex) {
						rs=null;
						ex.printStackTrace();
					}
				}
				// Statement对象关闭时,会自动释放其管理的一个ResultSet对象
				if(stmt != null){
					try {
						stmt.close();
						stmt=null;
					} catch (Exception ex) {
						stmt=null;
						ex.printStackTrace();
					}
				}
			}
		});
	}
	public void executeUpdate(String sql) {
		getSession().createSQLQuery(sql).executeUpdate();
	}

	public List<Map<String, Object>> findSQLList(String sql, Object... params) {
		Query query = getSession().createSQLQuery(sql);
		query = setQueryParams(query,params);
		return query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
	}

	public List<Map<String, Object>> findHQLList(String hql, Object... params) {
		Query query = getSession().createQuery(hql);
		query = setQueryParams(query,params);
		return query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
	}

	public Object getSqlUniqueResult(String sql, Object... params) {
		Query query = getSession().createSQLQuery(sql);
		query = setQueryParams(query,params);
		return query.uniqueResult();
	}

	public Object getHqlUniqueResult(String hql, Object... params) {
		Query query = getSession().createQuery(hql);
		query = setQueryParams(query,params);
		return query.uniqueResult();
	}

}
